﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;
using Jb.Common.Extensions;
using Jb.Domain;
using Jb.Web.ViewModels;
using Jb.Web.Utility;
using AutoMapper;

namespace Jb.Web.Controllers
{
    public class RegistrationController : BaseController
    {
		private JbEntities _Context = new JbEntities();
        
		#region Constructors
		public RegistrationController()
		{
		}

		public RegistrationController(UserViewModel currentUser)
			: base(currentUser)
        {
        }
		#endregion Constructors

		#region Action Methods

        public ActionResult JobSeeker()
        {
            RegisterModel viewModel = new RegisterModel();
            return View(viewModel);
        }

        /// <summary>
        /// Registers a JobSeeker Account with necessary and few Dummy Data 
        /// </summary>
        /// <param name="viewModel"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult JobSeeker(RegisterModel viewModel)
        {
            if(!ModelState.IsValid)
                return View(viewModel);
            if(_Context.IsDuplicateEmail(viewModel.Email))
            {
                ModelState.AddModelError("Email", "Sorry! this email is already in use, please choose another.");
                return View(viewModel);
            }

            using (System.Transactions.TransactionScope transaction = new System.Transactions.TransactionScope())
            {
                ///Create the User at First
                User user = new Domain.User();
                user.UserName = viewModel.Email;
                user.Password = viewModel.Password;
                user.IsActive = false;
                user.GroupID = ConfigReader.UserGroupIDOfJobSeeker;

                _Context.Users.AddObject(user);
                _Context.SaveChanges();

                ///Add the Job Seeker
                Jb.Domain.JobSeeker jobSeeker = WebUtil.BuildBlankJobSeeker(viewModel.Email, user.ID);
                _Context.JobSeekers.AddObject(jobSeeker);

                _Context.SaveChanges();
                ///Add the Relationship Between JobSeeker and User
                user.JobSeekerID = jobSeeker.ID;
                _Context.SaveChanges();

                ///Send Email Notification to the Job Seeker
                SendNotificationToJobSeeker(user, jobSeeker);

                transaction.Complete();
                
                return RedirectToAction("RegistrationSuccess", new { type = "JobSeeker" });
            }            
        }

        /// <summary>
        /// Company Registration
        /// </summary>
        /// <returns></returns>
        public ActionResult Company()
        {
            CompanyRegisterModel viewModel = new CompanyRegisterModel();
            return View(viewModel);
        }

        /// <summary>
        /// Registers a Company with user given short info and some dummey data in
        /// Company profile, Contact and Address 
        /// </summary>
        /// <param name="viewModel"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Company(CompanyRegisterModel viewModel)
        {
            viewModel.CompanyName = viewModel.CompanyName.Trim();
            viewModel.ContactName = viewModel.ContactName.Trim();

            if (!ModelState.IsValid)
                return View(viewModel);
            
            if (_Context.IsDuplicateCompanyName(viewModel.CompanyName))
            {
                ModelState.AddModelError("CompanyName", "Sorry! this company name already exists.");
                return View(viewModel);
            }
            if(_Context.IsDuplicateEmail(viewModel.Email))
            {
                ModelState.AddModelError("Email", "Sorry! this email is already taken.");
                return View(viewModel);
            }
            
            Company company = SaveDummyCompany(viewModel);

            //Send mail to the customer with the comany activation link
            SendActivationNotification(company, company.Contacts.ToList()[0]);
            //Send mail to the Admin about a new customer registration
            SendAdminNotification(company);

            ///Rebuild the Company Route Cache, and re-map them in the global routing cache
            MvcApplication.RefreshRoutes(true);

            return RedirectToAction("RegistrationSuccess", new { type = "Employeer" });
        }

        /// <summary>
        /// Shows registration success view for JobSeeker or Employer
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public ActionResult RegistrationSuccess(String type)
        {
            ViewData[AppConstants.ViewDataKeys.GENERIC_KEY] = type == "Employeer" ? "Employeer" : "JobSeeker"; 
            return View();
        }

		#endregion Action Methods
		
		#region Helper Methods

        /// <summary>
        /// Sends a notification to the Job Seeker with account activation link
        /// </summary>
        /// <param name="user"></param>
        /// <param name="jobSeeker"></param>
        private void SendNotificationToJobSeeker(Domain.User user, Domain.JobSeeker jobSeeker)
        {
            StringBuilder template = new StringBuilder(WebUtil.ReadEmailTemplate(AppConstants.EmailTemplate.COMMON));
            if (template.Length > 0)
            {
                StringBuilder sb = new StringBuilder();
                ///Job Seeker Details
                sb.AppendFormat("Dear Job Seeker,<br/>");
                sb.AppendFormat("Thank you for registering in {0}. ", ConfigReader.SiteName);
                sb.AppendFormat("Click on the following activation link to activate your account.<br/>");
                sb.AppendFormat("<a href='{0}/Account/Activate?ID={1}&Key={2}'>{0}/Account/Activate?ID={1}&Key={2}</a><br /><br />", WebUtil.GetDomainAddress(),
                    user.ID, jobSeeker.ActivationKey.ToString());
                sb.AppendFormat("<b>Note:</b> If you cannot click on the link then Copy it and Paste to your browser's address bar and press Enter in your keyboard to make your account active.<br/><br/>");
                sb.AppendFormat("After activation use following user name and password for login -.<br /><br />User Name: {0}<br />Password: {1}", user.UserName, user.Password);

                ///Basic Setup
                template.Replace(AppConstants.ETConstants.DOMAIN, WebUtil.GetDomainAddress());
                template.Replace(AppConstants.ETConstants.MESSAGE, sb.ToString());
                String fromEmail = ConfigReader.SupportEmail;
                String toEmail = String.Empty;//ConfigReader.AdminEmail;
                toEmail = user.UserName;

                String subject = String.Format("Activate your account in {0}.", ConfigReader.SiteName);
                WebUtil.SendMail(fromEmail, toEmail, String.Empty, String.Empty, subject, template.ToString());
            }
        }


        /// <summary>
        /// Builds Dummy company object along with associated contact, address and user object
        /// </summary>
        /// <param name="viewModel"></param>
        /// <returns></returns>
        private Domain.Company SaveDummyCompany(CompanyRegisterModel viewModel)
        {
            using (System.Transactions.TransactionScope transaction = new System.Transactions.TransactionScope())
            {   
                ///At first build an user object without the reference of contact
                User user = new User();
                user.UserName = viewModel.UserName;
                user.Password = viewModel.Password;
                //user.Contact = contact;
                user.GroupID = ConfigReader.UserGroupIDOfCompanyAdmin;
                _Context.AddToUsers(user);
                _Context.SaveChanges();

                ///Build an Empty Company with dummy data            
                Company company = new Company();
                company.Name = viewModel.CompanyName;
                company.ActivationKey = System.Guid.NewGuid();
                company.IsActive = false;
                company.IndustryTypeID = ConfigReader.DefaultIndustryTypeID;
                company.Url = company.Name.ToSeoUrl();

                ///Build an Address object and attach it with the company and Contact
                Contact contact = new Contact();
                contact.Name = viewModel.ContactName;
                contact.Gender = "M";
                contact.CreatedOn = contact.ModifiedOn = DateTime.Now;

                ///Build an Address Object for contact and Company                
                company.Address = new Address();
                company.Address.Email = AppConstants.ValueOf.UNKNOWN;

                contact.Address = new Address();
                contact.Address.Email = viewModel.Email;
                contact.Address.ZipCode = company.Address.ZipCode = AppConstants.ValueOf.UNKNOWN;
                contact.Address.AddressType = company.Address.AddressType = (int)AddressType.Permanent;
                contact.Address.CreatedOn = contact.Address.ModifiedOn = company.Address.CreatedOn = company.Address.ModifiedOn = company.CreatedOn = company.ModifiedOn = DateTime.Now;
                contact.Address.ModifiedBy = company.Address.ModifiedBy = user.ID;

                ///Save Company with address
                _Context.AddToCompanies(company);
                _Context.SaveChanges();

                ///Save the Contact with Address                
                _Context.AddToContacts(contact);
                contact.CompanyID = company.ID;                
                _Context.SaveChanges();

                ///Relate user with the newly created contact of this company                
                user.ContactID = contact.ID;
                _Context.SaveChanges();

                ///Reload a fresh copy of the newly created company
                Company newCompany = _Context.Companies.Include("Contacts").Include("Address").FirstOrDefault(P => P.ID == company.ID);
                transaction.Complete();
                ///Reload the full object from DB
                return newCompany;
            }
        }

        /// <summary>
        /// Sends a notification email with account Activation link to the given contact/company email.
        /// </summary>
        /// <param name="company"></param>
        /// <param name="contact"></param>
        private void SendActivationNotification(Company company, Contact contact)
        {
            StringBuilder template = new StringBuilder(WebUtil.ReadEmailTemplate(AppConstants.EmailTemplate.COMMON));
            if (template.Length > 0)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("Dear {0},<br/>", contact.Name.HtmlEncode());
                sb.AppendFormat("Thank you for registering your company <b>{0}</b> in {1}. Click on the link below to activate your account.<br /><br />", 
                    company.Name.HtmlEncode(), ConfigReader.SiteName);
                sb.AppendFormat("<a href='{0}/Company/Activate?ID={1}&Key={2}'>{0}/Company/Activate?ID={1}&Key={2}</a><br /><br />", 
                    WebUtil.GetDomainAddress(), company.ID, company.ActivationKey.ToString());
                sb.AppendFormat("<b>Note:</b> If you cannot click on the link then Copy it and Paste to your browser's address bar to make your account active.");
                ///Proejct Details
                //sb.Append("<br /><br />");
                template.Replace(AppConstants.ETConstants.DOMAIN, WebUtil.GetDomainAddress());
                template.Replace(AppConstants.ETConstants.MESSAGE, sb.ToString());
                String fromEmail = ConfigReader.SupportEmail;
                String toEmail = contact.Address.Email; //ConfigReader.AdminEmail;                

                String subject = String.Format("Activate your account in {0}.", ConfigReader.SiteName);
                WebUtil.SendMail(fromEmail, toEmail, String.Empty, String.Empty, subject, template.ToString());
            }
        }

        /// <summary>
        /// Sends a Notification to the Site Admin about the new company registration
        /// </summary>
        /// <param name="company"></param>
        private void SendAdminNotification(Company company)
        {
            StringBuilder template = new StringBuilder(WebUtil.ReadEmailTemplate(AppConstants.EmailTemplate.COMMON));
            if (template.Length > 0)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("Dear Admin,<br/>");
                sb.AppendFormat("A new company <b>{0}</b> has been registerd in {1}. Click on the link below to see details.<br /><br />", 
                    company.Name.HtmlEncode(), ConfigReader.SiteName);
                sb.AppendFormat("<a href='{0}/{1}'>{0}/{1}</a><br /><br />", WebUtil.GetDomainAddress(), company.Url);

                //sb.AppendFormat("<a href='{0}/Company/Profile/{1}/{2}'>{0}/Company/Profile/{1}/{2}</a><br /><br />", WebUtil.GetDomainAddress(),
                //    company.ID, company.Name.ToSeoUrl());
                ////sb.AppendFormat("<b>Note:</b> If you cannot click on the link then Copy it and Paste to your browser's address bar to make your account active.");
                ///Proejct Details
                //sb.Append("<br /><br />");
                template.Replace(AppConstants.ETConstants.DOMAIN, WebUtil.GetDomainAddress());
                template.Replace(AppConstants.ETConstants.MESSAGE, sb.ToString());
                String fromEmail = ConfigReader.SupportEmail;
                String toEmail = ConfigReader.AdminEmail;

                String subject = String.Format("New Company Registered in {0}.", ConfigReader.SiteName);
                WebUtil.SendMail(fromEmail, toEmail, String.Empty, String.Empty, subject, template.ToString());
            }
        }

        #endregion			
    }
}


